using System;
using System.Runtime.Serialization;
using OhioState.AssetManaged;
using OhioState.Math;

namespace OhioState.Graphics.Proxy
{
    [Serializable()]
    public class SphereProxy : SharedAsset, IDrawable
    {
        private SharedSphere sphere;
        private MaterialProxy material;

        #region Public Properties
        public IBoundingVolume BoundingVolume
        {
            get 
            { 
                return sphere.BSphere;
            }
        }

        public SharedSphere Sphere
        {
            get { return sphere; }
            set
            {
                IAssetManagedHandler changedEvent = new IAssetManagedHandler(FireUpdateChangedEvent);
                this.SetPropertyEventHandling(sphere, value, changedEvent);
                sphere = value;
                FireUpdateChangedEvent(this);
            }
        }

        public IMaterial Material
        {
            get { return material; }
            set
            {
                //
                // For fields that contain shared objects, follow this sequence:
                //   1. rewire the notification for the shared object
                //        this property points to.
                //   2. set the property.
                //   3. perform any internal updates.
                //   4. Implicit in step 3 would be changing this 
                //         object and hence notifying it's subscribers.
                //
                IAssetManagedHandler changedEvent = new IAssetManagedHandler(ChangedEvent);
                MaterialProxy mat = value as MaterialProxy;
                if (mat != null)
                {
                    this.SetPropertyEventHandling(material, mat, changedEvent);
                    material = mat;
                    changedEvent(mat);
                }
            }
        }

        public bool Wireframe { get; set; }
        #endregion Public Properties

        #region Constructors
        public SphereProxy(String name, SharedSphere sphere)
            : base(name)

        {
            this.Sphere = sphere;
            this.Material = MaterialProxy.White;
        }

        public SphereProxy(SharedSphere sphere)
            : this("Sphere", sphere)
        {
        }
        #endregion

        public virtual void Render(IRenderPanel panel)
        {
        }

        private void ChangedEvent(IAssetManaged obj)
        {
            FireUpdateChangedEvent(this);
        }

        /// <summary>
        /// Overrides shared object ToString method
        /// </summary>
        /// <returns>A string representing parent shared object name</returns>
        public override String ToString()
        {
            return base.Name;
        }

        public void Update(IRenderPanel panel)
        {
            FireUpdateChangedEvent(this);
        }

        public override void ReaquireAssets()
        {
            //
            // Use the Properties to ensure the old event handlers are removed and new
            //    ones are added. Particularly if we are setting an item to itself.
            //
            IAssetManaged item = AssetManager.Instance.Find(material.GetType(), material.Name);
            if (item != material)
            {
                this.Material = item as IMaterial;
            }
        }

        [OnDeserialized]
        private void OnDeserialized(StreamingContext context)
        {
            IAssetManagedHandler changedEvent = new IAssetManagedHandler(ChangedEvent);
            material.AddChangedEventHandler(changedEvent);
        }
    }
}
